<?php
/**
 * Created by PhpStorm.
 * User: kwibon
 * Date: 2019/1/10
 * Time: 16:50
 */

namespace app\api\controller;
use app\common\controller\Api;
use think\Config;
use think\Exception;
use think\log;
use think\Db;
use OSS\OssClient;
use OSS\Core\OssException;

class OssController extends Api
{
    public function _initialize()
    {
        header('Access-Control-Allow-Origin:*');
        Log::init([
            'type'  =>  'File',
            'path'  =>  APP_PATH.'logs/'
        ]);
    }

    public $bucket = 'kwibon-public-images';//Bucket名称

    /**
     * 实例化阿里云OSS
     * @return object 实例化得到的对象
     * 此步作为共用对象，可提供给多个模块统一调用
     */
    public function newOssClient(){
        $config=config('aliyun_oss');
        //实例化OSS
        vendor('OSS.autoload');//引入文件
        $oss = new \OSS\OssClient($config['accessKeyId'],$config['accessKeySecret'],$config['endpoint']);
        return $oss;
    }

    public function getSignature(){
        $config=config('aliyun_oss');

        $id= $config['accessKeyId'];          // 请填写您的AccessKeyId。
        $key= $config['accessKeySecret'];     // 请填写您的AccessKeySecret。
        $host = "http://".$this->bucket.".".$config['endpoint'];          // $host的格式为 bucketname.endpoint，请替换为您的真实信息。
        $dir = "custom/";                 // 用户上传文件时指定的前缀。

        $now = time();
        $expire = 600;  //设置该policy超时时间是100s. 即这个policy过了这个有效时间，将不能访问。
        $end = $now + $expire;
        $expiration = $this->gmt_iso8601($end);

        //最大文件大小.用户可以自己设置
        $condition = array(0=>'content-length-range', 1=>0, 2=>1048576000);
        $conditions[] = $condition;

        // 表示用户上传的数据，必须是以$dir开始，不然上传会失败，这一步不是必须项，只是为了安全起见，防止用户通过policy上传到别人的目录。
        $start = array(0=>'starts-with', 1=>'$key', 2=>$dir);
        $conditions[] = $start;

        $arr = array('expiration'=>$expiration,'conditions'=>$conditions);
        $policy = json_encode($arr);
        $base64_policy = base64_encode($policy);
        $string_to_sign = $base64_policy;
        $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $key, true));

        $response = array();
        $response['accessid'] = $id;
        $response['host'] = $host;
        $response['policy'] = $base64_policy;
        $response['signature'] = $signature;
        $response['expire'] = $end;
        $response['dir'] = $dir;

        return json_encode($response);
    }

    public function gmt_iso8601($time) {
        $dtStr = date("c", $time);
        $mydatetime = new \DateTime($dtStr);
        $expiration = $mydatetime->format(\DateTime::ISO8601);
        $pos = strpos($expiration, '+');
        $expiration = substr($expiration, 0, $pos);
        return $expiration."Z";
    }


    public function writeLog($msg){//记录日志   by Suley
        if(!$msg) return false;
        $dir = APP_PATH.'logs';
        $log = 'uploadOss_log';
        if(is_file($dir.'/'.$log)){
            $filesize = filesize($dir.'/'.$log);
            if($filesize>1048576){//设置log文件大小为1mb
                rename($dir.'/'.$log,$dir.'/'.$log."".date('YmdH',time()));
            }
        }
        $result = file_put_contents($dir.'/'.$log,(date('Y-m-d h:i:s',time())).'   '.$msg."\r\n",FILE_APPEND);
        return $result;
    }

    //上传本地图片到OSS
    public function sendLocalImgToOSS($imageSrc='')
    {
        if(empty($imageSrc)){
            return "";
        }
        if(substr($imageSrc,0,4)=='http'){
            return "";
        }
        $object = 'custom/'.md5($imageSrc.time()).".jpg";//想要保存文件的名称
        $file = $_SERVER['DOCUMENT_ROOT'].$imageSrc;//文件路径，必须是本地的
        $file = str_replace('\\', '/', $file);

        $config=config('aliyun_oss');
        $ossClient = $this->newOssClient();
        $ossClient->uploadFile($this->bucket,$object,$file);
        $ossimgurl = "https://".$this->bucket.".".$config['endpoint']."/".$object;
        //删除文件
        //unlink($file);
        return $ossimgurl;
    }

    //批量转移本地图片至OSS
    public function transferImg()
    {
        die;

        ignore_user_abort();//关闭浏览器仍然执行
        set_time_limit(0);//让程序一直执行下去

        $config=config('aliyun_oss');
        $ossClient = $this->newOssClient();

        $imgField = 'img_src';
        $where[$imgField] = array('like', '%uploads%');
        $dataArr = db("carousel")
            ->where($where)
            ->field("id,img_src")
            ->select();

        if(empty($dataArr)){
            echo "没有需要上传的图片";
            die;
        }

        foreach ($dataArr as $value) {
            $id = $value['id'];
            $imageSrc = $value[$imgField];
            if($imageSrc==''){
                continue;
            }

            if(substr($imageSrc,0,4)=='http'){
                continue;
            }
            $object = 'custom/'.md5($imageSrc.time()).".jpg";//想要保存文件的名称
            $file = $_SERVER['DOCUMENT_ROOT'].$imageSrc;//文件路径，必须是本地的
            $file = str_replace('\\', '/', $file);

            try{
                $ossClient->uploadFile($this->bucket,$object,$file);
                // 存储图片的oss路径
                $ossimgurl = "https://".$this->bucket.".".$config['endpoint']."/".$object;
                $newSrc = $ossimgurl;
                $this->writeLog("成功上传：【id=".$id."】");
                $this->writeLog("【".$ossimgurl."】");
                echo "*****************************<br>";
                echo "成功上传：【".$id."】<br>";
                echo "【".$ossimgurl."】<br>";
                echo "*****************************<br>";
            } catch(OssException $e) {
                $this->writeLog("上传到oss失败：".$id."原因为：".$e);
                $this->writeLog($imageSrc);
                echo "####################################################################<br>";
                echo "上传到oss失败：【".$id."】。原因为：".$e."<br>";
                echo "【".$imageSrc."】<br>";
                echo "####################################################################<br>";
                $newSrc = $imageSrc;
            }

            $updateArr[$imgField] = $newSrc;
            $res = db("carousel")->where("id",$id)->update($updateArr);

            $this->writeLog("更新结果：".$res);
            echo "更新结果：".$res."<br>";
            echo "####################################################################<br>";
        }

        die;
    }
    //参数说明
    // source_img=数据来源,
    //id=关联id,
    //width=高度缩放比例,
    //height=高度剪切比例,
    //water=是否添加水印 水印必须传 若不添加水印 ['type'=>'text']
    public function saveRemoteImgToOSS($source_img,$id=0,$w_scale=1,$h_scale=1,$water=[])
    {
        $config=config('aliyun_oss');
        $ossClient = $this->newOssClient();
        $filename = uniqid().".jpg";
        $imgContent = file_get_contents($source_img);
        $dir = APP_PATH.'logs/';
        $orignal_file = $dir.$filename;
        file_put_contents($orignal_file,$imgContent);
        //剪切图片
        if(($w_scale>0 && $w_scale<1) || ($h_scale>0 && $h_scale<1)){
            $image = \think\Image::open($orignal_file);
            // 返回图片的宽度
            $width = $image->width();
            // 返回图片的高度
            $height = $image->height();
            $image->thumb($width*$w_scale, $height*$h_scale,\think\Image::THUMB_CENTER)->save($orignal_file);
        }
        if(!empty($water) && isset($water['type']) && !empty($water['type'])){
            if(isset($water['type'])){
                $image = \think\Image::open($orignal_file);
                if($water['type']=="image"){
                    // 返回图片的宽度
                    $width = $image->width();
                    // 返回图片的高度
                    $height = $image->height();
                    //图片水印
                    $water_img = $this->getWaterImg($width,$height);
                    if(is_file($water_img)){
                        //右下角水印
                        $image->water($water_img,\think\Image::WATER_SOUTHEAST ,50)->save($orignal_file);
                    }
                }else{
                    //文字水印
                    if(isset($water['content'])){
                        $content = $water['content'];
                    }else{
                        $content = "";
                    }
                    $font_file = ROOT_PATH.'/public/font-zihun-19.ttf';
                    $image->text($content,$font_file,20,'#ffffff')->save($orignal_file);
                }
            }
        }
        $object = 'custom/'.md5($filename.time()).".jpg";//想要保存文件的名称
        try{
            $this->writeLog("开始上传：");
            $ossClient->uploadFile($this->bucket,$object,$orignal_file);
            // 存储图片的oss路径
            $ossimgurl = "https://".$this->bucket.".".$config['endpoint']."/".$object;

            $this->writeLog("success上传：【id=".$id."】");
            $this->writeLog("【".$ossimgurl."】");
            unlink($orignal_file);
            return $ossimgurl;
        } catch(OssException $e) {
            $this->writeLog("上传到oss failed：".$id."原因为：".$e);
            return "";
        }
    }

    public function getWaterImg($width,$height)
    {
        //高度大于1000
        if($height>1000){
            $water_img = ROOT_PATH.'/public/water_img200.png';

        }elseif($height>600){
            $water_img = ROOT_PATH.'/public/water_img100.png';

        }else{
            $water_img = ROOT_PATH.'/public/water_img50.png';

        }

        return $water_img;
    }
    //获取远程的OSS图片到本地
    public function getOssThumbImage($source_img,$imgdir,$type = 'product')
    {
        $filename = uniqid('',true).".jpg";
        $imgContent = file_get_contents($source_img);
//        $rootpath = "/var/www/html/php_test_station/fast_bank/";
        $rootpath = ROOT_PATH;
        $testDir = Config::get('baseTempImgDir');//线上
        if($type=='product'){
            $dir = $rootpath.'public'.DS.$testDir.DS.'p_'.$imgdir.DS;
            $img_url = DS.$testDir.DS.'p_'.$imgdir.DS;
        }else{
            $dir = $rootpath.'public'.DS.$testDir.DS.'t_'.$imgdir.DS;
            $img_url = DS.$testDir.DS.'t_'.$imgdir.DS;
        }
        if(!is_dir($dir)){
            mkdir($dir,0777,true);
            chmod($dir, 0777);
        }
        $orignal_file = $dir.$filename;
        file_put_contents($orignal_file,$imgContent);
        //剪切图片
        $image = \think\Image::open($orignal_file);
        $image->thumb(360,240,\think\Image::THUMB_CENTER)->save($orignal_file);
        return $img_url.$filename;
    }

    //获取oss缩略图
    public function getOssThumbImg($oss_img_url,$width=600,$height=400)
    {
        if(substr($oss_img_url,0,4)!=='http') return $oss_img_url;//本地图片直接返回地址
        $oss_img_url = empty($oss_img_url)?'':$oss_img_url.'?x-oss-process=image/resize,m_fill,h_'.$height.',w_'.$width;
        return str_replace('https','http',$oss_img_url);
    }
    //生成本地资源
    public function base64Upload($base64)
    {
        $data = explode(',', $base64);
        unset($base64);
        if (count($data) !== 2) {
            return '文件格式错误';
        }
        if (preg_match('/^(data:\s*image\/(\w+);base64)/', $data[0], $result)) {
            $type = $result[2];
            if (!in_array($type, array('jpeg', 'jpg', 'gif', 'bmp', 'png'))) {
                return '文件格式不在允许范围内';
            }
            $image_name = md5(uniqid()) . '.' . $result[2];
            $image_path = "./uploads/image/";
            $image_file = $image_path . $image_name;
            if (!file_exists($image_path)) {
                mkdir($image_path, 0777, true);
            }
            //服务器文件存储路径
            try {
                if (file_put_contents($image_file, base64_decode($data[1]))) {
                    return ['name' => $image_name, 'path' => $image_path];
                } else {
                    return '文件保存失败';
                }
            } catch (\Exception $e) {
                return $e->getMessage();
            }
        }
        return '文件格式错误';
    }
    //上传资源到OSS
    public function base64ToOss($base64){
        // OSS处理
        $result = $this->base64Upload($base64);//这个方法下面提供的有，根据代码封装位置是否静态调用，里面逻辑是先将二进制流上传到服务器本地，再通过下面的代码上传到oss，若成功上传到oss就删除刚才本地图片
        if (!is_array($result)) {
            return $result;
        }

        $fileResult  = &$result;
        $filePath    = $fileResult['path'] . $fileResult['name'];
        $ossFileName = implode('/', ['uploads/image', date('Ymd'), $fileResult['name']]);
        try {
            //实例化对象 将配置传入
            $ossClient = $this->newOssClient();
            $result    = $ossClient->uploadFile($this->bucket, $ossFileName, $filePath);

            return ['url'=>$result['info']['url']];
        } catch (OssException $e) {
            return $e->getMessage();
        } finally {
            unlink($filePath);
        }
    }
}